package com.gollum.web.service;

import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
import cloud.tianai.captcha.validator.ImageCaptchaValidator;
import cloud.tianai.captcha.validator.common.model.dto.ImageCaptchaTrack;
import cloud.tianai.captcha.validator.impl.BasicCaptchaTrackValidator;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.captcha.ShearCaptcha;
import cn.hutool.captcha.generator.MathGenerator;
import cn.hutool.core.util.IdUtil;
import com.gollum.common.constant.GollumCacheConstants;
import com.gollum.common.constant.NumberConstants;
import com.gollum.common.constant.SystemConstants;
import com.gollum.common.exception.BusinessException;
import com.gollum.common.utils.BeanUtils;
import com.gollum.common.utils.ServletUtils;
import com.gollum.common.utils.StringUtils;
import com.gollum.common.utils.ip.IpUtils;
import com.gollum.common.utils.redis.RedisCache;
import com.gollum.system.domain.request.CaptchaRequest;
import com.gollum.system.domain.response.CaptchaResponse;
import org.aspectj.apache.bcel.classfile.Code;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 验证码服务
 *
 * @author Herther
 * @version 1.0.0
 * @createTime 2022年08月28日 21:50:00
 */
@Component
public class CaptchaService {

    @Autowired
    protected ImageCaptchaGenerator imageCaptchaGenerator;

    @Autowired
    protected RedisCache redisCache;
    /** code **/
    public final String CODE = "code";
    /** token **/
    public final String TOKEN = "token";

    /**
     * 生成图片验证码
     *
     * @return CaptchaResponse 验证码对象
     * @auther: Herther
     * @version 1.0.0
     * @date: 2022/8/28 21:51
     */
    public CaptchaResponse generateCaptcha(){
        //现在默认生成滑块，后期拓展其他验证方式
        ImageCaptchaInfo imageCaptchaInfo =
                imageCaptchaGenerator.generateCaptchaImage(CaptchaTypeConstant.SLIDER);

        //扔到redis
        String token = setCaptchaCach(imageCaptchaInfo);
        CaptchaResponse captchaResponse = new CaptchaResponse();
        BeanUtils.copyBeanProp(imageCaptchaInfo, captchaResponse);
        captchaResponse.setToken(token);
        return captchaResponse;
    }

    /**
     * 校验验证码
     *
     * @auther: Herther
     * @version 1.0.0
     * @date: 2022/8/28 22:48
     */
    public void checkCaptcha(CaptchaRequest captchaRequest) {
        // TODO: 2022/8/28 后期需要加入用户名 用于保存验证码验证日志，还得在redis中添加 该用户名校验了验证码登录  参数校验处理 目前dev 暂时不加入
        ImageCaptchaValidator sliderCaptchaValidator = new BasicCaptchaTrackValidator();

        ImageCaptchaTrack imageCaptchaTrack = new ImageCaptchaTrack();
        BeanUtils.copyBeanProp(captchaRequest,imageCaptchaTrack);

        //获取redis中的校验验证码的数据
        Map<String,Object> captchaCach = (Map) redisCache.getCacheObject(captchaRequest.getToken());
        if (StringUtils.isNull(captchaCach)){
            throw new BusinessException("验证码已过期，不存在，请重新获取");
        }
        //获取完redis 的验证码数据立马删除
        redisCache.deleteObject(captchaRequest.getToken());
        //校验验证码
        boolean hasSuccess = sliderCaptchaValidator.valid(imageCaptchaTrack, captchaCach);
        if (!hasSuccess){
            throw new BusinessException("验证码不正确");
        }
    }





    /**
     * 将验证码的校验设置到 redis中用于下次校验
     * @param imageCaptchaInfo 生成的素材
     * @auther: Herther
     * @version 1.0.0
     * @date: 2022/8/28 22:22
     */
    private String setCaptchaCach(ImageCaptchaInfo imageCaptchaInfo){
        ImageCaptchaValidator imageCaptchaValidator
                = new BasicCaptchaTrackValidator();
        //生成校验的对象
        Map<String, Object> captchaValidData
                = imageCaptchaValidator.generateImageCaptchaValidData(imageCaptchaInfo);

        //生成uuid token 用作redis key
        String token = IdUtil.fastSimpleUUID();
        //设置缓存 10分钟过期
        redisCache.setCacheObject(token,captchaValidData,10, TimeUnit.MINUTES);
        return token;
    }


    /**
     * 生成图形验证码
     * @auther: Herther
     * @since 1.0.0
     * @date: 2022/11/17 22:27
     */
    public Map<String,String> genGrapCpatchaCode() {
        //圆圈验证码生成
        ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(102, 40, 4, 4);
        // 自定义验证码内容为四则运算方式
        captcha.setGenerator(new MathGenerator());
        // 重新生成code
        captcha.createCode();
        //生成 base64验证码
        String captchaCodeImgage = captcha.getImageBase64();

        //redis 存储操作
        String token = setRedisCaptchaCode(captcha.getCode());
        //返回
        Map<String,String> captchaMaps = new HashMap<String,String>(2);
        captchaMaps.put(CODE, captchaCodeImgage);
        captchaMaps.put(TOKEN, token);
        return captchaMaps;
    }

    /**
     * 获取用户的IP验证码存储到redis
     *
     * @auther: Herther
     * @since 1.0.0
     * @date: 2022/11/17 22:34
     */
    private String setRedisCaptchaCode(String code) {
        String token = IdUtil.simpleUUID();
        StringBuffer redisKey = new StringBuffer(GollumCacheConstants.CAPTCHA_GRAP_KEY)
                .append(token);
        //Redis 存储
        redisCache.setCacheObject(redisKey.toString(), code, NumberConstants.FIVE_STR_INT,TimeUnit.MINUTES);
        return token;
    }
}
